<?php

namespace App\Http\Controllers\Instorage;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use App\Models\Storage\Goods;
use App\Models\Storage\GoodsRecord;
use App\Models\Instorage\ProdEnsureOther;
use App\Models\Instorage\ProdEnsureImport;
use App\Models\Outstorage\OrderOutEnsure;
use Illuminate\Support\Facades\Cache;


class InBaseController extends Controller
{
    protected function inStorage(array $params, $model, $type)
    {
        if (empty($params)) {
            return '未选择入库商品！';
        }

        foreach ($params as $item) {
            if (empty($item['act_stock_no'])) return '库位必选！';
            if (empty($item['act_state_name'])) return '状态必选！';
            if (empty($item['act_number'])) return '数量必填！';
            if (empty($item['act_available_time'])) return '有效期必填！';
            if (empty($item['product'])) return '该商品未检索到数据，无法入库！';
            //检查入库单状态是否发生变化
            $tag = $model::where([
                ['related_id', '=', $item['id']],
                ['product_id', '=', $item['product']['id']]
            ])->first();
            if ($tag && $tag->number != $item['tag']['number']) return '入库单状态发生变化,请刷新页面！';
        }

        try {
            // 开启事务
            DB::beginTransaction();
            // 循环库位
            foreach ($params as $order) {
                //插入tag表
                $tag = $model::where([
                    ['related_id', '=', $order['id']],
                    ['product_id', '=', $order['product']['id']]
                ])->first();
                if ($tag) {
                    $tag->number = $tag->number + $order['act_number'];
                    $tag->save();
                } else {
                    $tagData = [
                        'related_id' => $order['id'],
                        'product_id' => $order['product']['id'],
                        'number' => $order['act_number'],
                        'created_at' => date('Y-m-d H:i:s'),
                    ];
                    $model::insert($tagData);
                }
                if ($type == 'prod_imp') {
                    $sum = DB::table($type)->where('InvoiceNo',$order['InvoiceNo'])->sum('ImportQnty');
                    $id =  DB::table($type)->where('InvoiceNo',$order['InvoiceNo'])->pluck('id');
                    $number = $model::whereIn('related_id',$id)->sum('number');
                    if($sum == $number){
                        DB::table($type)->where('InvoiceNo',$order['InvoiceNo'])->update(['state' => '已入库']);
                    }else{
                        DB::table($type)->where('InvoiceNo',$order['InvoiceNo'])->update(['state' => '入库中']);
                    }
                }
                if ($type == 'asn') {
                    $sum = DB::table($type)->where('CustomerOrderNo',$order['CustomerOrderNo'])->sum('InQnty');
                    $id =  DB::table($type)->where('CustomerOrderNo',$order['CustomerOrderNo'])->pluck('id');
                    $number = $model::whereIn('related_id',$id)->sum('number');
                    if($sum == $number){
                        DB::table($type)->where('CustomerOrderNo',$order['CustomerOrderNo'])->update(['state' => '已入库']);
                    }else{
                        DB::table($type)->where('CustomerOrderNo',$order['CustomerOrderNo'])->update(['state' => '入库中']);
                    }
                }
                if ($type == 'adj_out_dirt') {
                    $sum = DB::table($type)->where('OutStcNo',$order['OutStcNo'])->sum('AdjustQnty');
                    $id =  DB::table($type)->where('OutStcNo',$order['OutStcNo'])->pluck('id');
                    $number = $model::whereIn('related_id',$id)->sum('number');
                    if($sum == $number){
                        DB::table($type)->where('OutStcNo',$order['OutStcNo'])->update(['state' => '已入库']);
                    }else{
                        DB::table($type)->where('OutStcNo',$order['OutStcNo'])->update(['state' => '入库中']);
                    }
                }
                if ($type == 'move_in_dirt') {
                    $sum = DB::table($type)->where('InStcNo',$order['InStcNo'])->sum('MovAdmQnty');
                    $id =  DB::table($type)->where('InStcNo',$order['InStcNo'])->pluck('id');
                    $number = $model::whereIn('related_id',$id)->sum('number');
                    if($sum == $number){
                        DB::table($type)->where('InStcNo',$order['InStcNo'])->update(['state' => '已入库']);
                    }else{
                        DB::table($type)->where('InStcNo',$order['InStcNo'])->update(['state' => '入库中']);
                    }
                }
                if ($type == 'ret_in_dirt') {
                    $sum = DB::table($type)->where('InStcNo',$order['InStcNo'])->sum('AdmQnty');
                    $id =  DB::table($type)->where('InStcNo',$order['InStcNo'])->pluck('id');
                    $number = $model::whereIn('related_id',$id)->sum('number');
                    if($sum == $number){
                        DB::table($type)->where('InStcNo',$order['InStcNo'])->update(['state' => '已入库']);
                    }else{
                        DB::table($type)->where('InStcNo',$order['InStcNo'])->update(['state' => '入库中']);
                    }
                }
                // 插入goods表和副表
                $goodsData = [
                    'product_id' => $order['product']['id'],
                    'stock_no' => $order['act_stock_no'],
                    'state_name' => $order['act_state_name'],
                    'CHARG' => empty($order['act_CHARG']) ? '' : $order['act_CHARG'],
                    'available_time' => date('Ym', strtotime($order['act_available_time'])),
                ];
                if($type =='ret_in_dirt'){
                    $goodsData['odd'] = $order['OrderNo'];
                }
                if($type =='prod_imp'){
                    $goodsData['odd'] = $order['InvoiceNo'];
                }
                if($type =='asn'){
                    $goodsData['odd'] = $order['CustomerOrderNo'];
                }
                if($type =='move_in_dirt'){
                    $goodsData['odd'] = $order['MoveNo'];
                }
                if($type =='adj_out_dirt'){
                    $goodsData['odd'] = $order['AdjustNo'];
                }
                $goods = Goods::where($goodsData)->first();
                if ($goods) {
                    $goods->number += $order['act_number'];
                    $goods->save();
                } else {
                    $goodsData['number'] = $order['act_number'];
                    $goodsData['created_at'] = $goodsData['updated_at'] = date('Y-m-d H:i:s');
                    Goods::insert($goodsData);
                }
                $goodsData['type'] = $type;
                $goodsData['related_id'] = $order['id'];
                $goodsRecord = GoodsRecord::where($goodsData)->first();
                if ($goodsRecord) {
                    $goodsRecord->number += $order['act_number'];
                    $goodsRecord->save();
                } else {
                    GoodsRecord::insert($goodsData);
                }
            }
            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            return $e->getMessage();
        }

        return null;
    }

    protected function inConfirm(array $params, $model, $type)
    {
        if (empty($params)) {
            return '未选择确认商品！';
        }
        foreach ($params as $item) {
            if (empty($item['act_state_name'])) return '状态必选！';
            if (empty($item['act_number'])) return '数量必填！';
            //检查入库单状态是否发生变化
            $tag = $model::where([
                ['related_id', '=', $item['id']],
                ['product_id', '=', $item['product']['id']]
            ])->first();
            if ($tag && $tag->confirmNum != $item['tag']['confirmNum']) return '确认单状态发生变化,请刷新页面！';
        }

        try {
            // 开启事务
            DB::beginTransaction();
            // 循环库位
            foreach ($params as $order) {
                //插入tag表
                $tag = $model::where([
                    ['related_id', '=', $order['id']],
                    ['product_id', '=', $order['product']['id']]
                ])->first();
                $tag->confirmNum = $tag->confirmNum + $order['act_number'];
                $tag->save();
                if ($type == 'prod_imp') {
                    $sum = DB::table($type)->where('InvoiceNo',$order['InvoiceNo'])->sum('ImportQnty');
                    $id =  DB::table($type)->where('InvoiceNo',$order['InvoiceNo'])->pluck('id');
                    $confirmNum = $model::whereIn('related_id',$id)->sum('confirmNum');
                    if($sum == $confirmNum){
                        DB::table($type)->where('InvoiceNo',$order['InvoiceNo'])->update(['state' => '已回传']);
                    }
                }
                if ($type == 'asn') {
                    $sum = DB::table($type)->where('CustomerOrderNo',$order['CustomerOrderNo'])->sum('InQnty');
                    $id =  DB::table($type)->where('CustomerOrderNo',$order['CustomerOrderNo'])->pluck('id');
                    $confirmNum = $model::whereIn('related_id',$id)->sum('confirmNum');
                    if($sum == $confirmNum){
                        DB::table($type)->where('CustomerOrderNo',$order['CustomerOrderNo'])->update(['state' => '已回传']);
                    }
                }
                if ($type == 'move_in_dirt') {
                    $sum = DB::table($type)->where('InStcNo',$order['InStcNo'])->sum('MovAdmQnty');
                    $id =  DB::table($type)->where('InStcNo',$order['InStcNo'])->pluck('id');
                    $confirmNum = $model::whereIn('related_id',$id)->sum('confirmNum');
                    if($sum == $confirmNum){
                        DB::table($type)->where('InStcNo',$order['InStcNo'])->update(['state' => '已回传']);
                    }
                }
                if ($type == 'adj_out_dirt') {
                    $sum = DB::table($type)->where('OutStcNo',$order['OutStcNo'])->sum('AdjustQnty');
                    $id =  DB::table($type)->where('OutStcNo',$order['OutStcNo'])->pluck('id');
                    $confirmNum = $model::whereIn('related_id',$id)->sum('confirmNum');
                    if($sum == $confirmNum){
                        DB::table($type)->where('OutStcNo',$order['OutStcNo'])->update(['state' => '已回传']);
                    }
                }
                if ($type == 'ret_in_dirt') {
                    $sum = DB::table($type)->where('InStcNo',$order['InStcNo'])->sum('AdmQnty');
                    $id =  DB::table($type)->where('InStcNo',$order['InStcNo'])->pluck('id');
                    $confirmNum = $model::whereIn('related_id',$id)->sum('confirmNum');
                    if($sum == $confirmNum){
                        DB::table($type)->where('InStcNo',$order['InStcNo'])->update(['state' => '已回传']);
                    }
                }

                // goods表和副表
                $goodsData = [
                    'product_id' => $order['product']['id'],
                    'state_name' => '加工完成',
                ];
                $total = $order['act_number'];
                $goodsList = Goods::where($goodsData)->get();
                foreach ($goodsList as $goods) {
                    if ($total <= 0) break;
                    if ($goods->number <= $total) {
                        $total -= $goods->number;
                        $goods->state_name = $order['act_state_name'];
                        $goods->save();
                    } else {
                        $goods->number -= $total;
                        $goods->save();
                        $arr = [
                            'product_id' => $goods->product_id,
                            'stock_no' => $goods->stock_no,
                            'state_name' => $order['act_state_name'],
                            'CHARG' => $goods->CHARG,
                            'number' => $total,
                            'available_time' => $goods->available_time,
                            'created_at' => date('Y-m-d H:i:s'),
                            'updated_at' => date('Y-m-d H:i:s'),
                        ];
                        Goods::insert($arr);
                        $total = 0;
                    }
                }
            }

            // 生成TXT和插入
            $res = $this->inEnsure($type, $params);
            if ($res) throw new \Exception($res);
            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            return $e->getMessage();
        }

        return null;
    }

    private function inEnsure($type, $params)
    {
        $data = [];
        switch ($type) {
            case 'move_in_dirt':
                foreach ($params as $order) {
                    $data[$order['MoveNo']][] = $order;
                }
                $res = $this->insertIntoOther($type, $data);
                break;
            case 'prod_imp':
                foreach ($params as $order) {
                    $data[$order['InvoiceNo']][] = $order;
                }
                $res = $this->insertIntoOther($type, $data);
                break;
            case 'asn':
                foreach ($params as $order) {
                    $data[$order['CustomerOrderNo']][] = $order;
                }
                $res = $this->insertIntoImport($type, $data);
                break;
            case 'ret_in_dirt':
                foreach ($params as $order) {
                    $data[$order['OrderNo']][] = $order;
                }
                $res = $this->insertIntoOut($type, $data);
                break;
            case 'adj_out_dirt':
                foreach ($params as $order) {
                    $data[$order['AdjustNo']][] = $order;
                }
                $res = $this->insertIntoOut($type, $data);
                break;
        }

        return $res;
    }

    private function genTxt($type, $data)
    {
        $path = storage_path() . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'OUT' . DIRECTORY_SEPARATOR;
        switch ($type) {
            case 'move_in_dirt':
                $this->genOtherTxt($type, $data, $path);
                break;
            case 'prod_imp':
                $this->genOtherTxt($type, $data, $path);
                break;
            case 'asn':
                $this->genImportTxt($type, $data, $path);
                break;
            case 'ret_in_dirt':
                $this->genOutTxt($type, $data, $path, $data[0]['InStcNo']);
                break;
            case 'adj_out_dirt':
                $this->genOutTxt($type, $data, $path, $data[0]['OutStcNo']);
                break;
        }
        return null;
    }

    private function genOutTxt($type, $data, $path, $name)
    {
        if (Cache::get('generate_file_out') == 1) {
            $time = date('YmdHis',strtotime('+1second'));
        } else {
            Cache::put('generate_file_out', 1, 0.1);
            $time = date('YmdHis');
        }
        $fileName = 'OrdOutEnsure7858' . $time . $name . '.txt';
        $location = $path . $fileName;
        foreach ($data as $value) {
            $item = $this->getOutData($type, $value);
            if (!file_exists($location)) {
                file_put_contents($location, implode("\x08", array_keys($item)), FILE_APPEND);
            }
            file_put_contents($location, "\r\n" . implode("\x08", array_values($item)), FILE_APPEND);
        }
        $okName = 'LO0067858' . $time . '.ok';
        file_put_contents($path . $okName, $fileName . "\x08" . filesize($location));
    }

    private function genImportTxt($type, $data, $path)
    {
        if (Cache::get('generate_file_imp') == 1) {
            $time = date('YmdHis',strtotime('+1second'));
        } else {
            Cache::put('generate_file_imp', 1, 0.1);
            $time = date('YmdHis');
        }
        $fileName = 'ProdImpEnsureImport7858' . $time . '.txt';
        $location = $path . $fileName;
        foreach ($data as $value) {
            $item = $this->getImportData($type, $value);
            if (!file_exists($location)) {
                file_put_contents($location, implode("\x08", array_keys($item)), FILE_APPEND);
            }
            file_put_contents($location, "\r\n" . implode("\x08", array_values($item)), FILE_APPEND);
        }
        $okName = 'LO0047858' . $time . '.ok';
        file_put_contents($path . $okName, $fileName . "\x08" . filesize($location));
    }

    private function genOtherTxt($type, $data, $path)
    {
        if (Cache::get('generate_file_other') == 1) {
            $time = date('YmdHis',strtotime('+1second'));
        } else {
            Cache::put('generate_file_other', 1, 0.1);
            $time = date('YmdHis');
        }
        $fileName = 'ProdImpEnsureOther7858' . $time . '.txt';
        $location = $path . $fileName;
        foreach ($data as $value) {
            $item = $this->getOtherData($type, $value);
            if (!file_exists($location)) {
                file_put_contents($location, implode("\x08", array_keys($item)), FILE_APPEND);
            }
            file_put_contents($location, "\r\n" . implode("\x08", array_values($item)), FILE_APPEND);
        }
        $okName = 'LO0047858' . $time . '.ok';
        file_put_contents($path . $okName, $fileName . "\x08" . filesize($location));
    }

    private function insertIntoOther($type, $params)
    {
        switch ($type) {
            case 'move_in_dirt':
                foreach ($params as $val) {
                    $result = $this->genTxt($type, $val);
                    foreach ($val as $order) {
                        $data = $this->getOtherData($type, $order);
                        $data['created_at'] = date('Y-m-d H:i:s');
                        ProdEnsureOther::insert($data);
                    }
                }
                break;
            case 'prod_imp':
                foreach ($params as $val) {
                    $result = $this->genTxt($type, $val);
                    foreach ($val as $order) {
                        $data = $this->getOtherData($type, $order);
                        $data['created_at'] = date('Y-m-d H:i:s');
                        ProdEnsureOther::insert($data);
                    }
                }
                break;
        }

        return $result;
    }

    private function insertIntoOut($type, $params)
    {
        foreach ($params as $val) {
            $result = $this->genTxt($type, $val);
            foreach ($val as $order) {
                $data = $this->getOutData($type, $order);
                $data['created_at'] = date('Y-m-d H:i:s');
                OrderOutEnsure::insert($data);
            }
        }

        return $result;
    }

    private function getOutData($type, $order)
    {
        $data = [];
        switch ($type) {
            case 'ret_in_dirt':
                $data = [
                    'VBELN' => $order['InStcNo'],
                    'ISDD' => date('Ymd'),
                    'POSNR' => $order['LineNo'],
                    'MATNR' => $order['NewProductCd'],
                    'AdmQnty' => $order['act_number'],
                    'OrdTyep' => $order['AUART'],
                    'CHARG' => '00',
                    'WERKS' => '7858',
                    'LGORT' => $order['FineFlg'],
                    'PRODUCTCD' => $order['ProductCd'],
                ];
                break;
            case 'adj_out_dirt':
                $data = [
                    'VBELN' => $order['OutStcNo'],
                    'ISDD' => date('Ymd'),
                    'POSNR' => $order['LineNo'],
                    'MATNR' => $order['NewProductCd'],
                    'AdmQnty' => $order['act_number'],
                    'OrdTyep' => $order['AUART'],
                    'CHARG' => '00',
                    'WERKS' => '7858',
                    'LGORT' => $order['FineFlg'],
                    'PRODUCTCD' => $order['ProductCd'],
                ];
                break;
        }
        return $data;
    }

    private function getOtherData($type, $order)
    {
        $data = [];
        switch ($type) {
            case 'move_in_dirt':
                $data = [
                    'BLDAT' => date('Ymd', strtotime($order['created_at'])),
                    'BUDAT' => date('Ymd'),
                    'BKTXT' => '',
                    'MATNR' => $order['NewProductCd'],
                    'WERKS' => '7858',
                    'LGORT' => $order['act_state_name'],
                    'CHARG' => '00',
                    'ERFMG' => $order['act_number'],
                    'ERFME' => 'EA',
                    'EBELN' => $order['MoveNo'],
                    'EBELP' => $order['POSNR'],
                    'SGTXT' => '',
                    'UMWRK' => '',
                    'POSNR' => $order['LineNo'],
                    'VBELN' => $order['InStcNo'],
                    'LIFNR' => '',
                    'BSART' => $order['AUART'],
                    'PRODUCTCD' => $order['ProductCd'],
                ];
                break;
            case 'prod_imp':
                $data = [
                    'BLDAT' => date('Ymd', strtotime($order['created_at'])),
                    'BUDAT' => date('Ymd'),
                    'BKTXT' => '',
                    'MATNR' => $order['NewProductCd'],
                    'WERKS' => '7858',
                    'LGORT' => $order['act_state_name'],
                    'CHARG' => '00',
                    'ERFMG' => $order['act_number'],
                    'ERFME' => 'EA',
                    'EBELN' => $order['InvoiceNo'],
                    'EBELP' => $order['POSNR'],
                    'SGTXT' => '',
                    'UMWRK' => '',
                    'POSNR' => '',
                    'VBELN' => '',
                    'LIFNR' => '',
                    'BSART' => $order['BSART'],
                    'PRODUCTCD' => $order['ProductCd'],
                ];
                break;
        }
        return $data;
    }

    private function getImportData($type, $order)
    {
        $data = [];
        switch ($type) {
            case 'asn':
                $data = [
                    'BLDAT' => date('Ymd', strtotime($order['created_at'])),
                    'BUDAT' => date('Ymd'),
                    'BATXT' => $order['CustomerOrderNo'],
                    'MATNR' => $order['NewProductCD'],
                    'WERKS' => '7858',
                    'LGORT' => $order['LGORT'],
                    'CHARG' => '00',
                    'ERFMG' => $order['act_number'],
                    'ERFME' => 'EA',
                    'EBELN' => '',
                    'EBELP' => '',
                    'SGTXT' => '',
                    'UMLGO' => $order['act_state_name'],
                    'UMCHA' => '00',
                    'POSNR' => '',
                    'VBELN' => '',
                    'LIFER' => '',
                    'BSART' => 'EL',
                    'PRODUCTCD' => $order['ProductCD'],
                ];
                break;
        }
        return $data;
    }

    private function insertIntoImport($type, $params)
    {
        switch ($type) {
            case 'asn':
                foreach ($params as $val) {
                    $result = $this->genTxt($type, $val);
                    foreach ($val as $order) {
                        $data = $this->getImportData($type, $order);
                        $data['created_at'] = date('Y-m-d H:i:s');
                        ProdEnsureImport::insert($data);
                    }
                }
                break;
        }

        return $result;
    }
}